import java.awt.*;
 
//Complex Number Class.
class ComplexNumber {
    public final double real, imaginary;
    
    public ComplexNumber(double real, double imaginary)  
    {
        this.real = real;
        this.imaginary = imaginary;
    }

    public ComplexNumber()  
    { 
    	this(0, 0); 
    }
    
    public ComplexNumber(ComplexNumber cn)  
    { 
    	this(cn.real, cn.imaginary); 
    }
     
    public ComplexNumber add(ComplexNumber x) 
    {
        return new ComplexNumber(real + x.real, imaginary + x.imaginary);
    }
 
    public ComplexNumber multiply (ComplexNumber x) 
    {
    	return new ComplexNumber((real * x.real) - (imaginary * x.imaginary),
    							 (real * x.imaginary) + (imaginary * x.real));
    }
 
    public double getMagnitude() 
    { 
    	return Math.sqrt(real*real + imaginary*imaginary); 
    }           
}
 
class MandelbrotCanvas1 extends Canvas{
    boolean draw = false;
    final int size = 900;
    int depth = 250;
    
    //Power used in the fractal formula
    public int thePower = 2;
    
    //Real and Imaginary components used as the initial z in the fractal formulas.
    public double theStartX = 0;
    public double theStartY = 0;
    
    //Variables to hold green blue and red values to decide color values of fractal.
    public int theGreen = 20;
    public int theBlue = 100;
    public int theRed = 50;
    
    //real and imaginary thresholds used to determine step sizes.
    public double lx = -1.5;
    public double ly = -1.25;
    public double ux = 0.6;
    public double uy = 1.25;
    
    ComplexNumber[][] cnSet = new ComplexNumber[size][size];
    
    //Initializes the Mandelbrot frame and computes the initial Complex Number Set.
    MandelbrotCanvas1(){
         this.makecnSet();
    }
     
     //Paints the set if draw is set to true.
    public void paint(Graphics g){
        if (draw)
        {
            for (int i = 0; i < size; i++)
            {
                for (int j = 0; j < size; j++)
                {
                    int iterations = getIterations(cnSet[i][j],thePower);
                    g.setColor((iterations==depth) ? Color.BLACK : new Color((iterations*theRed) % 254, (iterations*theGreen) % 254, (iterations*theBlue) % 254) );
                    g.fillRect(i,j,1,1);
                }
            }
        }
    }

    //Method to get the number of iterations before the Magnitude breaks out.  Used for coloring.
    private int getIterations(ComplexNumber c,int y)
    {
    	//New complex number based on the starting real (x) and imaginary (y) components.
        ComplexNumber z = new ComplexNumber(theStartX, theStartY);
        int iterations = 0;

        for(; iterations < depth; iterations++) 
        {
        	//Break out condition.
            if (z.getMagnitude() > 4 )
            {
            	break; 
            }
            //Performs the formula change depending on the power of the desired fractal.
            for(int i = 1; i < y; i++)
            {
            z = z.multiply(z);
            }
            
            z = z.add(c);
        }

        return iterations;
    }

    //Sets draw to true.
    public void draw(){draw = true;}

//Makes the set of complex numbers to generate the fractal with.
	public void makecnSet() 
	{
		double xStep = (ux - lx)/size;
        double yStep = (uy - ly)/size;
       
        for( int i = 0; i < size; i ++){
           for (int j = 0; j < size; j++){
               cnSet[i][j] = new ComplexNumber(lx + i*xStep, uy - j*yStep);
           }
       }
		
	}

//Code to refresh the Mandelbrot viewer.
	public void refresh() 
	{
		   depth = 250;
		   thePower = 2;
		   theStartX = 0;
		   theStartY = 0;
		   theGreen = 20;
		   theBlue = 100;
		   theRed = 50;
		   lx = -1.5;
		   ly = -1.25;
		   ux = 0.6;
		   uy = 1.25;
	}

}
